From 52f5eeab68fa6e1618932f6e5bd2d2da58af7f53 Mon Sep 17 00:00:00 2001 From: Lars Hamann Date: Fri, 30 Oct 1998 19:57:50 +0000 Subject: [PATCH] free undo_un/selection, unselect list_item before disconnect signal Fri Oct 30 20:02:36 1998 Lars Hamann * gtk/gtklist.c (gtk_list_remove_items_internal): free undo_un/selection, unselect list_item before disconnect signal functions (gtk_list_destroy): removed. gtk_list_shutdown clears the list already (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): new functions. These functions are signal connected to inserted list_items, to handle key bindings and GtkItem::de/select/toggle signals. * gtk/gtklistitem.c (gtk_list_item_class_init): added missing gtk_object_class_add_signals call. (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) (gtk_list_item_start_selection) (gtk_list_item_end_selection) (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): removed. These functions are handled via connected gtk_list_signal_* functions now --- ChangeLog | 28 + ChangeLog.pre-2-0 | 28 + ChangeLog.pre-2-10 | 28 + ChangeLog.pre-2-2 | 28 + ChangeLog.pre-2-4 | 28 + ChangeLog.pre-2-6 | 28 + ChangeLog.pre-2-8 | 28 + gtk/gtklist.c | 3312 ++++++++++++++++++++++++-------------------- gtk/gtklistitem.c | 187 +-- 9 files changed, 2046 insertions(+), 1649 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0508147f9..42b0fbd919 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index a0508147f9..42b0fbd919 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,31 @@ +Fri Oct 30 20:02:36 1998 Lars Hamann + + * gtk/gtklist.c (gtk_list_remove_items_internal): + free undo_un/selection, unselect list_item before disconnect + signal functions + (gtk_list_destroy): removed. gtk_list_shutdown clears the list + already + (gtk_list_signal_item_select) (gtk_list_signal_item_deselect) + (gtk_list_signal_item_toggle) (gtk_list_signal_scroll_horizontal) + (gtk_list_signal_toggle_focus_row) (gtk_list_signal_select_all) + (gtk_list_signal_unselect_all) (gtk_list_signal_undo_selection) + (gtk_list_signal_start_selection) (gtk_list_signal_end_selection) + (gtk_list_signal_toggle_add_mode) (gtk_list_signal_scroll_vertical) + (gtk_list_signal_extend_selection) (gtk_list_signal_focus_lost): + new functions. These functions are signal connected to inserted + list_items, to handle key bindings and GtkItem::de/select/toggle + signals. + + * gtk/gtklistitem.c (gtk_list_item_class_init): added missing + gtk_object_class_add_signals call. + (gtk_list_item_toggle_focus_row) (gtk_list_item_select_all) + (gtk_list_item_unselect_all) (gtk_list_item_undo_selection) + (gtk_list_item_start_selection) (gtk_list_item_end_selection) + (gtk_list_item_extend_selection) (gtk_list_item_scroll_horizontal) + (gtk_list_item_scroll_vertical) (gtk_list_item_toggle_add_mode): + removed. These functions are handled via connected + gtk_list_signal_* functions now + Fri Oct 30 05:24:43 1998 Tim Janik * gtk/Makefile.am: cause the built sources to be rebuild when possible, diff --git a/gtk/gtklist.c b/gtk/gtklist.c index 6ce42f7308..a0318615b9 100644 --- a/gtk/gtklist.c +++ b/gtk/gtklist.c @@ -31,13 +31,21 @@ enum { #define SCROLL_TIME 100 +/** GtkList Methods **/ static void gtk_list_class_init (GtkListClass *klass); static void gtk_list_init (GtkList *list); + +/** GtkObject Methods **/ static void gtk_list_shutdown (GtkObject *object); -static void gtk_list_destroy (GtkObject *object); + +/** GtkWidget Methods **/ +static void gtk_list_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_list_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_list_realize (GtkWidget *widget); static void gtk_list_map (GtkWidget *widget); static void gtk_list_unmap (GtkWidget *widget); -static void gtk_list_realize (GtkWidget *widget); static void gtk_list_draw (GtkWidget *widget, GdkRectangle *area); static gint gtk_list_expose (GtkWidget *widget, @@ -48,48 +56,87 @@ static gint gtk_list_button_press (GtkWidget *widget, GdkEventButton *event); static gint gtk_list_button_release (GtkWidget *widget, GdkEventButton *event); -static void gtk_list_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_list_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void gtk_list_add (GtkContainer *container, - GtkWidget *widget); -static void gtk_list_remove (GtkContainer *container, - GtkWidget *widget); -static void gtk_list_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); - -static void gtk_real_list_select_child (GtkList *list, - GtkWidget *child); -static void gtk_real_list_unselect_child (GtkList *list, - GtkWidget *child); - - -static void gtk_list_set_anchor (GtkList *list, - gboolean add_mode, - gint anchor, - GtkWidget *undo_focus_child); -static void gtk_list_fake_unselect_all (GtkList *list, - GtkWidget *item); -static void gtk_list_fake_toggle_row (GtkList *list, - GtkWidget *item); -static void gtk_list_move_focus_child (GtkList *list, - GtkScrollType scroll_type, - gfloat position); -static void gtk_list_update_extended_selection (GtkList *list, - gint row); -static void gtk_list_focus_lost (GtkWidget *item, - GdkEventKey *event, - GtkList *list); -static void gtk_list_set_focus_child (GtkContainer *container, - GtkWidget *widget); -static gint gtk_list_focus (GtkContainer *container, - GtkDirectionType direction); - - -static GtkType gtk_list_child_type (GtkContainer *container); + +/** GtkContainer Methods **/ +static void gtk_list_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_list_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_list_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GtkType gtk_list_child_type (GtkContainer *container); +static void gtk_list_set_focus_child (GtkContainer *container, + GtkWidget *widget); +static gint gtk_list_focus (GtkContainer *container, + GtkDirectionType direction); + +/** GtkList Private Functions **/ +static void gtk_list_move_focus_child (GtkList *list, + GtkScrollType scroll_type, + gfloat position); +static gint gtk_list_horizontal_timeout (GtkWidget *list); +static gint gtk_list_vertical_timeout (GtkWidget *list); +static void gtk_list_remove_items_internal (GtkList *list, + GList *items, + gboolean no_unref); + +/** GtkList Selection Methods **/ +static void gtk_real_list_select_child (GtkList *list, + GtkWidget *child); +static void gtk_real_list_unselect_child (GtkList *list, + GtkWidget *child); + +/** GtkList Selection Functions **/ +static void gtk_list_set_anchor (GtkList *list, + gboolean add_mode, + gint anchor, + GtkWidget *undo_focus_child); +static void gtk_list_fake_unselect_all (GtkList *list, + GtkWidget *item); +static void gtk_list_fake_toggle_row (GtkList *list, + GtkWidget *item); +static void gtk_list_update_extended_selection (GtkList *list, + gint row); + +/** GtkListItem Signal Functions **/ +static void gtk_list_signal_focus_lost (GtkWidget *item, + GdkEventKey *event, + GtkList *list); +static void gtk_list_signal_toggle_focus_row (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_select_all (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_unselect_all (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_undo_selection (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_start_selection (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_end_selection (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_extend_selection (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + gboolean auto_start_selection, + GtkList *list); +static void gtk_list_signal_scroll_horizontal (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + GtkList *list); +static void gtk_list_signal_scroll_vertical (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + GtkList *list); +static void gtk_list_signal_toggle_add_mode (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_item_select (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_item_deselect (GtkListItem *list_item, + GtkList *list); +static void gtk_list_signal_item_toggle (GtkListItem *list_item, + GtkList *list); static GtkContainerClass *parent_class = NULL; @@ -168,7 +215,6 @@ gtk_list_class_init (GtkListClass *class) gtk_object_class_add_signals (object_class, list_signals, LAST_SIGNAL); object_class->shutdown = gtk_list_shutdown; - object_class->destroy = gtk_list_destroy; widget_class->map = gtk_list_map; widget_class->unmap = gtk_list_unmap; @@ -193,12 +239,6 @@ gtk_list_class_init (GtkListClass *class) class->unselect_child = gtk_real_list_unselect_child; } -static GtkType -gtk_list_child_type (GtkContainer *container) -{ - return GTK_TYPE_LIST_ITEM; -} - static void gtk_list_init (GtkList *list) { @@ -229,526 +269,478 @@ gtk_list_new (void) return GTK_WIDGET (gtk_type_new (GTK_TYPE_LIST)); } + +/* Private GtkObject Methods : + * + * gtk_list_shutdown + */ static void gtk_list_shutdown (GtkObject *object) { gtk_list_clear_items (GTK_LIST (object), 0, -1); - GTK_OBJECT_CLASS (parent_class)->shutdown (object); } + +/* Private GtkWidget Methods : + * + * gtk_list_size_request + * gtk_list_size_allocate + * gtk_list_realize + * gtk_list_map + * gtk_list_unmap + * gtk_list_motion_notify + * gtk_list_button_press + * gtk_list_button_release + */ static void -gtk_list_destroy (GtkObject *object) +gtk_list_size_request (GtkWidget *widget, + GtkRequisition *requisition) { - GList *node; - - GtkList *list = GTK_LIST (object); + GtkList *list; + GtkWidget *child; + GList *children; - for (node = list->children; node; node = node->next) - { - GtkWidget *child; + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST (widget)); + g_return_if_fail (requisition != NULL); - child = (GtkWidget *)node->data; - gtk_widget_ref (child); - gtk_widget_unparent (child); - gtk_widget_destroy (child); - gtk_widget_unref (child); - } - g_list_free (list->children); - list->children = NULL; + list = GTK_LIST (widget); + requisition->width = 0; + requisition->height = 0; - for (node = list->selection; node; node = node->next) + children = list->children; + while (children) { - GtkWidget *child; + child = children->data; + children = children->next; - child = (GtkWidget *)node->data; - gtk_widget_unref (child); - } - g_list_free (list->selection); - list->selection = NULL; + if (GTK_WIDGET_VISIBLE (child)) + { + gtk_widget_size_request (child, &child->requisition); - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (*GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} + requisition->width = MAX (requisition->width, + child->requisition.width); + requisition->height += child->requisition.height; + } + } -void -gtk_list_end_drag_selection (GtkList *list) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + requisition->width += GTK_CONTAINER (list)->border_width * 2; + requisition->height += GTK_CONTAINER (list)->border_width * 2; - list->drag_selection = FALSE; - if (GTK_WIDGET_HAS_GRAB (list)) - { - gtk_grab_remove (GTK_WIDGET (list)); - gdk_pointer_ungrab (GDK_CURRENT_TIME); - } - if (list->htimer) - { - gtk_timeout_remove (list->htimer); - list->htimer = 0; - } - if (list->vtimer) - { - gtk_timeout_remove (list->vtimer); - list->vtimer = 0; - } + requisition->width = MAX (requisition->width, 1); + requisition->height = MAX (requisition->height, 1); } -void -gtk_list_insert_items (GtkList *list, - GList *items, - gint position) +static void +gtk_list_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - GtkWidget *widget; - GList *tmp_list; - GList *last; - gint nchildren; + GtkList *list; + GtkWidget *child; + GtkAllocation child_allocation; + GList *children; - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST (widget)); + g_return_if_fail (allocation != NULL); - if (!items) - return; + list = GTK_LIST (widget); - gtk_list_end_drag_selection (list); - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) - gtk_list_end_selection (list); + widget->allocation = *allocation; + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); - tmp_list = items; - while (tmp_list) + if (list->children) { - widget = tmp_list->data; - tmp_list = tmp_list->next; + child_allocation.x = GTK_CONTAINER (list)->border_width; + child_allocation.y = GTK_CONTAINER (list)->border_width; + child_allocation.width = MAX (1, allocation->width - + child_allocation.x * 2); - gtk_widget_set_parent (widget, GTK_WIDGET (list)); - gtk_signal_connect (GTK_OBJECT (widget), "focus_out_event", - GTK_SIGNAL_FUNC (gtk_list_focus_lost), list); + children = list->children; - if (GTK_WIDGET_VISIBLE (widget->parent)) + while (children) { - if (GTK_WIDGET_REALIZED (widget->parent) && - !GTK_WIDGET_REALIZED (widget)) - gtk_widget_realize (widget); + child = children->data; + children = children->next; - if (GTK_WIDGET_MAPPED (widget->parent) && - !GTK_WIDGET_MAPPED (widget)) - gtk_widget_map (widget); - } - } + if (GTK_WIDGET_VISIBLE (child)) + { + child_allocation.height = child->requisition.height; - nchildren = g_list_length (list->children); - if ((position < 0) || (position > nchildren)) - position = nchildren; + gtk_widget_size_allocate (child, &child_allocation); - if (position == nchildren) - { - if (list->children) - { - tmp_list = g_list_last (list->children); - tmp_list->next = items; - items->prev = tmp_list; - } - else - { - list->children = items; + child_allocation.y += child_allocation.height; + } } } - else - { - tmp_list = g_list_nth (list->children, position); - last = g_list_last (items); - - if (tmp_list->prev) - tmp_list->prev->next = items; - last->next = tmp_list; - items->prev = tmp_list->prev; - tmp_list->prev = last; +} - if (tmp_list == list->children) - list->children = items; - } +static void +gtk_list_realize (GtkWidget *widget) +{ + GdkWindowAttr attributes; + gint attributes_mask; - if (list->children && !list->selection && - (list->selection_mode == GTK_SELECTION_BROWSE)) - { - widget = list->children->data; - gtk_list_select_child (list, widget); - } + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST (widget)); - if (GTK_WIDGET_VISIBLE (list)) - gtk_widget_queue_resize (GTK_WIDGET (list)); -} + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); -void -gtk_list_append_items (GtkList *list, - GList *items) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - gtk_list_insert_items (list, items, -1); -} + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; -void -gtk_list_prepend_items (GtkList *list, - GList *items) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); - gtk_list_insert_items (list, items, 0); + widget->style = gtk_style_attach (widget->style, widget->window); + gdk_window_set_background (widget->window, + &widget->style->base[GTK_STATE_NORMAL]); } static void -gtk_list_remove_items_internal (GtkList *list, - GList *items, - gboolean no_unref) +gtk_list_map (GtkWidget *widget) { - GtkWidget *widget; - GtkWidget *new_focus_child; - GtkWidget *old_focus_child; - GtkContainer *container; - GList *selected_widgets; - GList *tmp_list; - GList *work; - gboolean grab_focus = FALSE; - - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + GtkList *list; + GtkWidget *child; + GList *children; - if (!items) - return; - - container = GTK_CONTAINER (list); + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST (widget)); - gtk_list_end_drag_selection (list); - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) - gtk_list_end_selection (list); + GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + list = GTK_LIST (widget); - - tmp_list = items; - selected_widgets = NULL; - widget = NULL; - old_focus_child = new_focus_child = container->focus_child; + gdk_window_show (widget->window); - while (tmp_list) + children = list->children; + while (children) { - widget = tmp_list->data; - - tmp_list = tmp_list->next; - - if (no_unref) - gtk_widget_ref (widget); - - gtk_signal_disconnect_by_func - (GTK_OBJECT (widget), GTK_SIGNAL_FUNC (gtk_list_focus_lost), list); - + child = children->data; + children = children->next; - if (widget == new_focus_child) - { - work = g_list_find (list->children, widget); - - if (work) - { - if (work->next) - new_focus_child = work->next->data; - else if (list->children != work && work->prev) - new_focus_child = work->prev->data; - else - new_focus_child = NULL; - - if (GTK_WIDGET_HAS_FOCUS (widget)) - grab_focus = TRUE; - } - } - - list->children = g_list_remove (list->children, widget); - - if (widget->state == GTK_STATE_SELECTED) - selected_widgets = g_list_prepend (selected_widgets, widget); - else - gtk_widget_unparent (widget); - } - - if (selected_widgets) - { - tmp_list = selected_widgets; - while (tmp_list) - { - widget = tmp_list->data; - tmp_list = tmp_list->next; - - gtk_list_unselect_child (list, widget); - - gtk_widget_unparent (widget); - } - - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); - } - - g_list_free (selected_widgets); - - if (new_focus_child && new_focus_child != old_focus_child) - { - if (grab_focus) - gtk_widget_grab_focus (new_focus_child); - else - gtk_container_set_focus_child (container, new_focus_child); + if (GTK_WIDGET_VISIBLE (child) && + !GTK_WIDGET_MAPPED (child)) + gtk_widget_map (child); } - - if (GTK_WIDGET_VISIBLE (list)) - gtk_widget_queue_resize (GTK_WIDGET (list)); } -void -gtk_list_remove_items (GtkList *list, - GList *items) +static void +gtk_list_unmap (GtkWidget *widget) { - gtk_list_remove_items_internal (list, items, FALSE); -} + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST (widget)); -void -gtk_list_remove_items_no_unref (GtkList *list, - GList *items) -{ - gtk_list_remove_items_internal (list, items, TRUE); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); + gdk_window_hide (widget->window); } -void -gtk_list_clear_items (GtkList *list, - gint start, - gint end) +static gint +gtk_list_motion_notify (GtkWidget *widget, + GdkEventMotion *event) { - GtkWidget *widget; - GList *start_list; - GList *end_list; - GList *tmp_list; - guint nchildren; - - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); - - nchildren = g_list_length (list->children); - - if (nchildren > 0) - { - gboolean selection_changed; + GtkList *list; + GtkWidget *item = NULL; + GtkAdjustment *adj; + GtkContainer *container; + GList *work; + gint x; + gint y; + gint row = -1; + gint focus_row = 0; + gint length = 0; - if ((end < 0) || (end > nchildren)) - end = nchildren; + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); - if (start >= end) - return; + list = GTK_LIST (widget); - start_list = g_list_nth (list->children, start); - end_list = g_list_nth (list->children, end); + if (!list->drag_selection || !list->children) + return FALSE; - gtk_list_end_drag_selection (list); - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) - gtk_list_end_selection (list); + container = GTK_CONTAINER (widget); - if (start_list->prev) - start_list->prev->next = end_list; - if (end_list && end_list->prev) - end_list->prev->next = NULL; - if (end_list) - end_list->prev = start_list->prev; - if (start_list == list->children) - list->children = end_list; + if (event->is_hint || event->window != widget->window) + gdk_window_get_pointer (widget->window, &x, &y, NULL); - selection_changed = FALSE; - widget = NULL; - tmp_list = start_list; + adj = gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id); - while (tmp_list) + /* horizontal autoscrolling */ + if (adj && widget->allocation.width > adj->page_size && + (x < adj->value || x >= adj->value + adj->page_size)) + { + if (list->htimer == 0) { - widget = tmp_list->data; - tmp_list = tmp_list->next; - - if (widget->state == GTK_STATE_SELECTED) + list->htimer = gtk_timeout_add + (SCROLL_TIME, (GtkFunction) gtk_list_horizontal_timeout, widget); + + if (!((x < adj->value && adj->value <= 0) || + (x > adj->value + adj->page_size && + adj->value >= adj->upper - adj->page_size))) { - gtk_list_unselect_child (list, widget); - selection_changed = TRUE; - } + gfloat value; - gtk_widget_unparent (widget); - } + if (x < adj->value) + value = adj->value + (x - adj->value) / 2 - 1; + else + value = adj->value + 1 + (x - adj->value - adj->page_size) / 2; - g_list_free (start_list); + gtk_adjustment_set_value (adj, + CLAMP (value, 0.0, + adj->upper - adj->page_size)); + } + } + else + return FALSE; + } - if (list->children && !list->selection && - (list->selection_mode == GTK_SELECTION_BROWSE)) + + /* vertical autoscrolling */ + for (work = list->children; work; length++, work = work->next) + { + if (row < 0) { - widget = list->children->data; - gtk_list_select_child (list, widget); + item = GTK_WIDGET (work->data); + if (item->allocation.y > y || + (item->allocation.y <= y && + item->allocation.y + item->allocation.height > y)) + row = length; } - else if (selection_changed) - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); - gtk_widget_queue_resize (GTK_WIDGET (list)); + if (work->data == container->focus_child) + focus_row = length; } -} - -void -gtk_list_select_item (GtkList *list, - gint item) -{ - GList *tmp_list; + + if (row < 0) + row = length - 1; - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + if (list->vtimer != 0) + return FALSE; - tmp_list = g_list_nth (list->children, item); - if (tmp_list) - gtk_list_select_child (list, GTK_WIDGET (tmp_list->data)); -} + if (!((y < 0 && focus_row == 0) || + (y > widget->allocation.height && focus_row >= length - 1))) + list->vtimer = gtk_timeout_add (SCROLL_TIME, + (GtkFunction) gtk_list_vertical_timeout, + list); -void -gtk_list_unselect_item (GtkList *list, - gint item) -{ - GList *tmp_list; + if (row != focus_row) + gtk_widget_grab_focus (item); + + switch (list->selection_mode) + { + case GTK_SELECTION_BROWSE: + gtk_list_select_child (list, item); + break; + + case GTK_SELECTION_EXTENDED: + gtk_list_update_extended_selection (list, row); + break; - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + default: + break; + } - tmp_list = g_list_nth (list->children, item); - if (tmp_list) - gtk_list_unselect_child (list, GTK_WIDGET (tmp_list->data)); + return FALSE; } -void -gtk_list_select_child (GtkList *list, - GtkWidget *child) +static gint +gtk_list_button_press (GtkWidget *widget, + GdkEventButton *event) { - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECT_CHILD], child); -} + GtkList *list; + GtkWidget *item; -void -gtk_list_unselect_child (GtkList *list, - GtkWidget *child) -{ - gtk_signal_emit (GTK_OBJECT (list), list_signals[UNSELECT_CHILD], child); -} + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); -gint -gtk_list_child_position (GtkList *list, - GtkWidget *child) -{ - GList *children; - gint pos; + if (event->button != 1) + return FALSE; - g_return_val_if_fail (list != NULL, -1); - g_return_val_if_fail (GTK_IS_LIST (list), -1); - g_return_val_if_fail (child != NULL, -1); + list = GTK_LIST (widget); + item = gtk_get_event_widget ((GdkEvent*) event); - pos = 0; - children = list->children; + while (item && !GTK_IS_LIST_ITEM (item)) + item = item->parent; - while (children) + if (item && (item->parent == widget)) { - if (child == GTK_WIDGET (children->data)) - return pos; + gint last_focus_row; + gint focus_row; - pos += 1; - children = children->next; - } + if (event->type == GDK_BUTTON_PRESS) + { + list->drag_selection = TRUE; + gdk_pointer_grab (widget->window, TRUE, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, event->time); + gtk_grab_add (widget); + } + else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) + gtk_list_end_drag_selection (list); + + if (!GTK_WIDGET_HAS_FOCUS(item)) + gtk_widget_grab_focus (item); - return -1; -} + if (list->add_mode) + { + list->add_mode = FALSE; + gtk_widget_queue_draw (item); + } + + switch (list->selection_mode) + { + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: + if (event->type != GDK_BUTTON_PRESS) + gtk_list_select_child (list, item); + else + list->undo_focus_child = item; + break; + + case GTK_SELECTION_BROWSE: + break; -void -gtk_list_set_selection_mode (GtkList *list, - GtkSelectionMode mode) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + case GTK_SELECTION_EXTENDED: + focus_row = g_list_index (list->children, item); - if (list->selection_mode == mode) - return; + if (list->last_focus_child) + last_focus_row = g_list_index (list->children, + list->last_focus_child); + else + { + last_focus_row = focus_row; + list->last_focus_child = item; + } - list->selection_mode = mode; + if (event->type != GDK_BUTTON_PRESS) + { + if (list->anchor >= 0) + { + gtk_list_update_extended_selection (list, focus_row); + gtk_list_end_selection (list); + } + gtk_list_select_child (list, item); + break; + } + + if (event->state & GDK_CONTROL_MASK) + { + if (event->state & GDK_SHIFT_MASK) + { + if (list->anchor < 0) + { + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; - switch (mode) - { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_BROWSE: - gtk_list_unselect_all (list); - break; + list->anchor = last_focus_row; + list->drag_pos = last_focus_row; + list->undo_focus_child = list->last_focus_child; + } + gtk_list_update_extended_selection (list, focus_row); + } + else + { + if (list->anchor < 0) + gtk_list_set_anchor (list, TRUE, + focus_row, list->last_focus_child); + else + gtk_list_update_extended_selection (list, focus_row); + } + break; + } - default: - break; + if (event->state & GDK_SHIFT_MASK) + { + gtk_list_set_anchor (list, FALSE, + last_focus_row, list->last_focus_child); + gtk_list_update_extended_selection (list, focus_row); + break; + } + + if (list->anchor < 0) + gtk_list_set_anchor (list, FALSE, focus_row, + list->last_focus_child); + else + gtk_list_update_extended_selection (list, focus_row); + break; + + default: + break; + } } -} + return FALSE; +} -static void -gtk_list_map (GtkWidget *widget) +static gint +gtk_list_button_release (GtkWidget *widget, + GdkEventButton *event) { GtkList *list; - GtkWidget *child; - GList *children; + GtkWidget *item; - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST (widget)); + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); - GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); list = GTK_LIST (widget); - gdk_window_show (widget->window); + /* we don't handle button 2 and 3 */ + if (event->button != 1) + return FALSE; - children = list->children; - while (children) + if (list->drag_selection) { - child = children->data; - children = children->next; - - if (GTK_WIDGET_VISIBLE (child) && - !GTK_WIDGET_MAPPED (child)) - gtk_widget_map (child); - } -} - -static void -gtk_list_unmap (GtkWidget *widget) -{ - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST (widget)); - - GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); - gdk_window_hide (widget->window); -} - -static void -gtk_list_realize (GtkWidget *widget) -{ - GdkWindowAttr attributes; - gint attributes_mask; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST (widget)); - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + gtk_list_end_drag_selection (list); - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + switch (list->selection_mode) + { + case GTK_SELECTION_EXTENDED: + if (!(event->state & GDK_SHIFT_MASK)) + gtk_list_end_selection (list); + break; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); - gdk_window_set_user_data (widget->window, widget); + item = gtk_get_event_widget ((GdkEvent*) event); + + while (item && !GTK_IS_LIST_ITEM (item)) + item = item->parent; + + if (item && item->parent == widget) + { + if (list->undo_focus_child == item) + gtk_list_toggle_row (list, item); + } + list->undo_focus_child = NULL; + break; - widget->style = gtk_style_attach (widget->style, widget->window); - gdk_window_set_background (widget->window, - &widget->style->base[GTK_STATE_NORMAL]); + default: + break; + } + } + + return FALSE; } static void @@ -814,1033 +806,1154 @@ gtk_list_expose (GtkWidget *widget, return FALSE; } + +/* GtkContainer Methods : + * gtk_list_add + * gtk_list_remove + * gtk_list_forall + * gtk_list_child_type + * gtk_list_set_focus_child + * gtk_list_focus + */ static void -move_horizontal (GtkList *list, - GtkAdjustment *adj, - gint diff) +gtk_list_add (GtkContainer *container, + GtkWidget *widget) { - gfloat upper; - - adj->value += diff; + GList *item_list; - upper = adj->upper - adj->page_size; - adj->value = MIN (adj->value, upper); - adj->value = MAX (adj->value, 0.0); + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_LIST (container)); + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_LIST_ITEM (widget)); - gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed"); + item_list = g_list_alloc (); + item_list->data = widget; + + gtk_list_append_items (GTK_LIST (container), item_list); } -static gint -horizontal_timeout (GtkWidget *list) +static void +gtk_list_remove (GtkContainer *container, + GtkWidget *widget) { - gint x, y; - GdkEventMotion event; - GdkModifierType mask; - - g_return_val_if_fail (GTK_IS_LIST (list), FALSE); + GList *item_list; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_LIST (container)); + g_return_if_fail (widget != NULL); + g_return_if_fail (container == GTK_CONTAINER (widget->parent)); + + item_list = g_list_alloc (); + item_list->data = widget; + + gtk_list_remove_items (GTK_LIST (container), item_list); + + g_list_free (item_list); +} - GTK_LIST (list)->htimer = 0; - gdk_window_get_pointer (list->window, &x, &y, &mask); - - event.is_hint = 0; - event.x = x; - event.y = y; - event.state = mask; - - gtk_list_motion_notify (list, &event); - - return FALSE; -} - -static gint -vertical_timeout (GtkWidget *list) +static void +gtk_list_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) { - gint x; - gint y; - GdkEventMotion event; - GdkModifierType mask; + GtkList *list; + GtkWidget *child; + GList *children; - g_return_val_if_fail (GTK_IS_LIST (list), FALSE); + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_LIST (container)); + g_return_if_fail (callback != NULL); - GTK_LIST (list)->vtimer = 0; - gdk_window_get_pointer (list->window, &x, &y, &mask); + list = GTK_LIST (container); + children = list->children; - event.is_hint = 0; - event.x = x; - event.y = y; - event.state = mask; + while (children) + { + child = children->data; + children = children->next; - gtk_list_motion_notify (list, &event); + (* callback) (child, callback_data); + } +} - return FALSE; +static GtkType +gtk_list_child_type (GtkContainer *container) +{ + return GTK_TYPE_LIST_ITEM; } -static gint -gtk_list_motion_notify (GtkWidget *widget, - GdkEventMotion *event) +static void +gtk_list_set_focus_child (GtkContainer *container, + GtkWidget *child) { GtkList *list; - GtkWidget *item = NULL; - GtkAdjustment *adj; - GtkContainer *container; - GList *work; - gint x; - gint y; - gint row = -1; - gint focus_row = 0; - gint length = 0; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - list = GTK_LIST (widget); - - if (!list->drag_selection || !list->children) - return FALSE; - container = GTK_CONTAINER (widget); + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_LIST (container)); - if (event->is_hint || event->window != widget->window) - gdk_window_get_pointer (widget->window, &x, &y, NULL); + if (child) + g_return_if_fail (GTK_IS_WIDGET (child)); - adj = gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id); + list = GTK_LIST (container); + list->last_focus_child = container->focus_child; - /* horizontal autoscrolling */ - if (adj && widget->allocation.width > adj->page_size && - (x < adj->value || x >= adj->value + adj->page_size)) + if (child != container->focus_child) { - if (list->htimer == 0) - { - list->htimer = gtk_timeout_add - (SCROLL_TIME, (GtkFunction) horizontal_timeout, widget); - - if (!((x < adj->value && adj->value <= 0) || - (x > adj->value + adj->page_size && - adj->value >= adj->upper - adj->page_size))) - { - if (x < adj->value) - move_horizontal (list, adj, - 1 + (x - adj->value) / 2 ); - else - move_horizontal (list, adj, - 1 + (x - adj->value - adj->page_size) / 2); - } - } - else - return FALSE; + if (container->focus_child) + gtk_widget_unref (container->focus_child); + container->focus_child = child; + if (container->focus_child) + gtk_widget_ref (container->focus_child); } - - /* vertical autoscrolling */ - for (work = list->children; work; length++, work = work->next) + /* check for v adjustment */ + if (container->focus_child) { - if (row < 0) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y > y || - (item->allocation.y <= y && - item->allocation.y + item->allocation.height > y)) - row = length; - } + GtkAdjustment *adjustment; - if (work->data == container->focus_child) - focus_row = length; + adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), + vadjustment_key_id); + if (adjustment) + gtk_adjustment_clamp_page (adjustment, + container->focus_child->allocation.y, + (container->focus_child->allocation.y + + container->focus_child->allocation.height)); } - - if (row < 0) - row = length - 1; - - if (list->vtimer != 0) - return FALSE; - if (!((y < 0 && focus_row == 0) || - (y > widget->allocation.height && focus_row >= length - 1))) - list->vtimer = gtk_timeout_add (SCROLL_TIME, - (GtkFunction) vertical_timeout, list); - - if (row != focus_row) - gtk_widget_grab_focus (item); - switch (list->selection_mode) { case GTK_SELECTION_BROWSE: - gtk_list_select_child (list, item); - break; - - case GTK_SELECTION_EXTENDED: - gtk_list_update_extended_selection (list, row); + if (child) + gtk_list_select_child (list, child); break; - default: break; } - - return FALSE; } static gint -gtk_list_button_press (GtkWidget *widget, - GdkEventButton *event) +gtk_list_focus (GtkContainer *container, + GtkDirectionType direction) { - GtkList *list; - GtkWidget *item; + gint return_val = FALSE; - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (container != NULL, FALSE); + g_return_val_if_fail (GTK_IS_LIST (container), FALSE); - if (event->button != 1) - return FALSE; + if (!GTK_WIDGET_SENSITIVE (container)) + return_val = FALSE; + else if (container->focus_child == NULL || + !GTK_WIDGET_HAS_FOCUS (container->focus_child)) + { + if (*GTK_CONTAINER_CLASS (parent_class)->focus) + return_val = GTK_CONTAINER_CLASS (parent_class)->focus + (container, direction); + } + + if (!return_val) + { + GtkList *list; - list = GTK_LIST (widget); - item = gtk_get_event_widget ((GdkEvent*) event); + list = GTK_LIST (container); + if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + gtk_list_end_selection (list); + } - while (item && !GTK_IS_LIST_ITEM (item)) - item = item->parent; + return return_val; +} - if (item && (item->parent == widget)) + +/* Public GtkList Methods : + * + * gtk_list_insert_items + * gtk_list_append_items + * gtk_list_prepend_items + * gtk_list_remove_items + * gtk_list_remove_items_no_unref + * gtk_list_clear_items + * + * gtk_list_child_position + */ +void +gtk_list_insert_items (GtkList *list, + GList *items, + gint position) +{ + GtkWidget *widget; + GList *tmp_list; + GList *last; + gint nchildren; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + if (!items) + return; + + gtk_list_end_drag_selection (list); + if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + gtk_list_end_selection (list); + + tmp_list = items; + while (tmp_list) { - gint last_focus_row; - gint focus_row; + widget = tmp_list->data; + tmp_list = tmp_list->next; - if (event->type == GDK_BUTTON_PRESS) + gtk_widget_set_parent (widget, GTK_WIDGET (list)); + gtk_signal_connect (GTK_OBJECT (widget), "focus_out_event", + GTK_SIGNAL_FUNC (gtk_list_signal_focus_lost), + list); + gtk_signal_connect (GTK_OBJECT (widget), "toggle_focus_row", + GTK_SIGNAL_FUNC (gtk_list_signal_toggle_focus_row), + list); + gtk_signal_connect (GTK_OBJECT (widget), "select_all", + GTK_SIGNAL_FUNC (gtk_list_signal_select_all), + list); + gtk_signal_connect (GTK_OBJECT (widget), "unselect_all", + GTK_SIGNAL_FUNC (gtk_list_signal_unselect_all), + list); + gtk_signal_connect (GTK_OBJECT (widget), "undo_selection", + GTK_SIGNAL_FUNC (gtk_list_signal_undo_selection), + list); + gtk_signal_connect (GTK_OBJECT (widget), "start_selection", + GTK_SIGNAL_FUNC (gtk_list_signal_start_selection), + list); + gtk_signal_connect (GTK_OBJECT (widget), "end_selection", + GTK_SIGNAL_FUNC (gtk_list_signal_end_selection), + list); + gtk_signal_connect (GTK_OBJECT (widget), "extend_selection", + GTK_SIGNAL_FUNC (gtk_list_signal_extend_selection), + list); + gtk_signal_connect (GTK_OBJECT (widget), "scroll_horizontal", + GTK_SIGNAL_FUNC (gtk_list_signal_scroll_horizontal), + list); + gtk_signal_connect (GTK_OBJECT (widget), "scroll_vertical", + GTK_SIGNAL_FUNC (gtk_list_signal_scroll_vertical), + list); + gtk_signal_connect (GTK_OBJECT (widget), "toggle_add_mode", + GTK_SIGNAL_FUNC (gtk_list_signal_toggle_add_mode), + list); + gtk_signal_connect (GTK_OBJECT (widget), "select", + GTK_SIGNAL_FUNC (gtk_list_signal_item_select), + list); + gtk_signal_connect (GTK_OBJECT (widget), "deselect", + GTK_SIGNAL_FUNC (gtk_list_signal_item_deselect), + list); + gtk_signal_connect (GTK_OBJECT (widget), "toggle", + GTK_SIGNAL_FUNC (gtk_list_signal_item_toggle), + list); + + if (GTK_WIDGET_VISIBLE (widget->parent)) { - list->drag_selection = TRUE; - gdk_pointer_grab (widget->window, TRUE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, event->time); - gtk_grab_add (widget); + if (GTK_WIDGET_REALIZED (widget->parent) && + !GTK_WIDGET_REALIZED (widget)) + gtk_widget_realize (widget); + + if (GTK_WIDGET_MAPPED (widget->parent) && + !GTK_WIDGET_MAPPED (widget)) + gtk_widget_map (widget); } - else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) - gtk_list_end_drag_selection (list); - - if (!GTK_WIDGET_HAS_FOCUS(item)) - gtk_widget_grab_focus (item); + } - if (list->add_mode) + nchildren = g_list_length (list->children); + if ((position < 0) || (position > nchildren)) + position = nchildren; + + if (position == nchildren) + { + if (list->children) { - list->add_mode = FALSE; - gtk_widget_queue_draw (item); + tmp_list = g_list_last (list->children); + tmp_list->next = items; + items->prev = tmp_list; } - - switch (list->selection_mode) + else { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: - if (event->type != GDK_BUTTON_PRESS) - gtk_list_select_child (list, item); - else - list->undo_focus_child = item; - break; - - case GTK_SELECTION_BROWSE: - break; + list->children = items; + } + } + else + { + tmp_list = g_list_nth (list->children, position); + last = g_list_last (items); - case GTK_SELECTION_EXTENDED: - focus_row = g_list_index (list->children, item); + if (tmp_list->prev) + tmp_list->prev->next = items; + last->next = tmp_list; + items->prev = tmp_list->prev; + tmp_list->prev = last; - if (list->last_focus_child) - last_focus_row = g_list_index (list->children, - list->last_focus_child); - else - { - last_focus_row = focus_row; - list->last_focus_child = item; - } + if (tmp_list == list->children) + list->children = items; + } - if (event->type != GDK_BUTTON_PRESS) - { - if (list->anchor >= 0) - { - gtk_list_update_extended_selection (list, focus_row); - gtk_list_end_selection (list); - } - gtk_list_select_child (list, item); - break; - } - - if (event->state & GDK_CONTROL_MASK) - { - if (event->state & GDK_SHIFT_MASK) - { - if (list->anchor < 0) - { - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; + if (list->children && !list->selection && + (list->selection_mode == GTK_SELECTION_BROWSE)) + { + widget = list->children->data; + gtk_list_select_child (list, widget); + } - list->anchor = last_focus_row; - list->drag_pos = last_focus_row; - list->undo_focus_child = list->last_focus_child; - } - gtk_list_update_extended_selection (list, focus_row); - } - else - { - if (list->anchor < 0) - gtk_list_set_anchor (list, TRUE, - focus_row, list->last_focus_child); - else - gtk_list_update_extended_selection (list, focus_row); - } - break; - } + if (GTK_WIDGET_VISIBLE (list)) + gtk_widget_queue_resize (GTK_WIDGET (list)); +} - if (event->state & GDK_SHIFT_MASK) - { - gtk_list_set_anchor (list, FALSE, - last_focus_row, list->last_focus_child); - gtk_list_update_extended_selection (list, focus_row); - break; - } +void +gtk_list_append_items (GtkList *list, + GList *items) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - if (list->anchor < 0) - gtk_list_set_anchor (list, FALSE, focus_row, - list->last_focus_child); - else - gtk_list_update_extended_selection (list, focus_row); - break; - - default: - break; - } - } + gtk_list_insert_items (list, items, -1); +} - return FALSE; +void +gtk_list_prepend_items (GtkList *list, + GList *items) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + gtk_list_insert_items (list, items, 0); } -static gint -gtk_list_button_release (GtkWidget *widget, - GdkEventButton *event) +void +gtk_list_remove_items (GtkList *list, + GList *items) { - GtkList *list; - GtkWidget *item; + gtk_list_remove_items_internal (list, items, FALSE); +} - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_LIST (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); +void +gtk_list_remove_items_no_unref (GtkList *list, + GList *items) +{ + gtk_list_remove_items_internal (list, items, TRUE); +} - list = GTK_LIST (widget); +void +gtk_list_clear_items (GtkList *list, + gint start, + gint end) +{ + GtkWidget *widget; + GList *start_list; + GList *end_list; + GList *tmp_list; + guint nchildren; - /* we don't handle button 2 and 3 */ - if (event->button != 1) - return FALSE; + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - if (list->drag_selection) + nchildren = g_list_length (list->children); + + if (nchildren > 0) { + gboolean selection_changed; + + if ((end < 0) || (end > nchildren)) + end = nchildren; + + if (start >= end) + return; + + start_list = g_list_nth (list->children, start); + end_list = g_list_nth (list->children, end); + gtk_list_end_drag_selection (list); + if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + gtk_list_end_selection (list); - switch (list->selection_mode) - { - case GTK_SELECTION_EXTENDED: - if (!(event->state & GDK_SHIFT_MASK)) - gtk_list_end_selection (list); - break; + if (start_list->prev) + start_list->prev->next = end_list; + if (end_list && end_list->prev) + end_list->prev->next = NULL; + if (end_list) + end_list->prev = start_list->prev; + if (start_list == list->children) + list->children = end_list; - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: + selection_changed = FALSE; + widget = NULL; + tmp_list = start_list; - item = gtk_get_event_widget ((GdkEvent*) event); - - while (item && !GTK_IS_LIST_ITEM (item)) - item = item->parent; - - if (item && item->parent == widget) + while (tmp_list) + { + widget = tmp_list->data; + tmp_list = tmp_list->next; + + if (widget->state == GTK_STATE_SELECTED) { - if (list->undo_focus_child == item) - gtk_list_toggle_row (list, item); + gtk_list_unselect_child (list, widget); + selection_changed = TRUE; } - list->undo_focus_child = NULL; - break; - default: - break; + gtk_widget_unparent (widget); + } + + g_list_free (start_list); + + if (list->children && !list->selection && + (list->selection_mode == GTK_SELECTION_BROWSE)) + { + widget = list->children->data; + gtk_list_select_child (list, widget); } + else if (selection_changed) + gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); + + gtk_widget_queue_resize (GTK_WIDGET (list)); } - - return FALSE; } -static void -gtk_list_size_request (GtkWidget *widget, - GtkRequisition *requisition) +gint +gtk_list_child_position (GtkList *list, + GtkWidget *child) { - GtkList *list; - GtkWidget *child; GList *children; + gint pos; - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST (widget)); - g_return_if_fail (requisition != NULL); + g_return_val_if_fail (list != NULL, -1); + g_return_val_if_fail (GTK_IS_LIST (list), -1); + g_return_val_if_fail (child != NULL, -1); + + pos = 0; + children = list->children; + + while (children) + { + if (child == GTK_WIDGET (children->data)) + return pos; + + pos += 1; + children = children->next; + } + + return -1; +} + + +/* Private GtkList Insert/Remove Item Functions: + * + * gtk_list_remove_items_internal + */ +static void +gtk_list_remove_items_internal (GtkList *list, + GList *items, + gboolean no_unref) +{ + GtkWidget *widget; + GtkWidget *new_focus_child; + GtkWidget *old_focus_child; + GtkContainer *container; + GList *tmp_list; + GList *work; + gboolean grab_focus = FALSE; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + if (!items) + return; + + container = GTK_CONTAINER (list); + + gtk_list_end_drag_selection (list); + if (list->selection_mode == GTK_SELECTION_EXTENDED) + { + if (list->anchor >= 0) + gtk_list_end_selection (list); + + if (list->undo_selection || list->undo_unselection) + { + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; + + list->anchor = -1; + list->drag_pos = -1; + list->undo_focus_child = container->focus_child; + } + } + + tmp_list = items; + while (tmp_list) + { + widget = tmp_list->data; + tmp_list = tmp_list->next; + + if (widget->state == GTK_STATE_SELECTED) + gtk_list_unselect_child (list, widget); - list = GTK_LIST (widget); - requisition->width = 0; - requisition->height = 0; + } - children = list->children; - while (children) + tmp_list = items; + old_focus_child = new_focus_child = container->focus_child; + + while (tmp_list) { - child = children->data; - children = children->next; + widget = tmp_list->data; + tmp_list = tmp_list->next; + + if (no_unref) + gtk_widget_ref (widget); + - if (GTK_WIDGET_VISIBLE (child)) + if (widget == new_focus_child) { - gtk_widget_size_request (child, &child->requisition); + work = g_list_find (list->children, widget); - requisition->width = MAX (requisition->width, child->requisition.width); - requisition->height += child->requisition.height; + if (work) + { + if (work->next) + new_focus_child = work->next->data; + else if (list->children != work && work->prev) + new_focus_child = work->prev->data; + else + new_focus_child = NULL; + + if (GTK_WIDGET_HAS_FOCUS (widget)) + grab_focus = TRUE; + } } - } - requisition->width += GTK_CONTAINER (list)->border_width * 2; - requisition->height += GTK_CONTAINER (list)->border_width * 2; - - requisition->width = MAX (requisition->width, 1); - requisition->height = MAX (requisition->height, 1); + gtk_signal_disconnect_by_data (GTK_OBJECT (widget), (gpointer) list); + list->children = g_list_remove (list->children, widget); + gtk_widget_unparent (widget); + } + + if (new_focus_child && new_focus_child != old_focus_child) + { + if (grab_focus) + gtk_widget_grab_focus (new_focus_child); + else + gtk_container_set_focus_child (container, new_focus_child); + } + + if (GTK_WIDGET_VISIBLE (list)) + gtk_widget_queue_resize (GTK_WIDGET (list)); } -static void -gtk_list_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkList *list; - GtkWidget *child; - GtkAllocation child_allocation; - GList *children; - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST (widget)); - g_return_if_fail (allocation != NULL); +/* Public GtkList Selection Methods : + * + * gtk_list_set_selection_mode + * gtk_list_select_item + * gtk_list_unselect_item + * gtk_list_select_child + * gtk_list_unselect_child + * gtk_list_select_all + * gtk_list_unselect_all + * gtk_list_extend_selection + * gtk_list_end_drag_selection + * gtk_list_start_selection + * gtk_list_end_selection + * gtk_list_toggle_row + * gtk_list_toggle_focus_row + * gtk_list_toggle_add_mode + * gtk_list_undo_selection + */ +void +gtk_list_set_selection_mode (GtkList *list, + GtkSelectionMode mode) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - list = GTK_LIST (widget); + if (list->selection_mode == mode) + return; - widget->allocation = *allocation; - if (GTK_WIDGET_REALIZED (widget)) - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); + list->selection_mode = mode; - if (list->children) + switch (mode) { - child_allocation.x = GTK_CONTAINER (list)->border_width; - child_allocation.y = GTK_CONTAINER (list)->border_width; - child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2); - - children = list->children; + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_BROWSE: + gtk_list_unselect_all (list); + break; - while (children) - { - child = children->data; - children = children->next; + default: + break; + } +} - if (GTK_WIDGET_VISIBLE (child)) - { - child_allocation.height = child->requisition.height; +void +gtk_list_select_item (GtkList *list, + gint item) +{ + GList *tmp_list; - gtk_widget_size_allocate (child, &child_allocation); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - child_allocation.y += child_allocation.height; - } - } - } + tmp_list = g_list_nth (list->children, item); + if (tmp_list) + gtk_list_select_child (list, GTK_WIDGET (tmp_list->data)); } -static void -gtk_list_add (GtkContainer *container, - GtkWidget *widget) +void +gtk_list_unselect_item (GtkList *list, + gint item) { - GList *item_list; + GList *tmp_list; - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_LIST (container)); - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_LIST_ITEM (widget)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - item_list = g_list_alloc (); - item_list->data = widget; - - gtk_list_append_items (GTK_LIST (container), item_list); + tmp_list = g_list_nth (list->children, item); + if (tmp_list) + gtk_list_unselect_child (list, GTK_WIDGET (tmp_list->data)); } -static void -gtk_list_remove (GtkContainer *container, - GtkWidget *widget) +void +gtk_list_select_child (GtkList *list, + GtkWidget *child) { - GList *item_list; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_LIST (container)); - g_return_if_fail (widget != NULL); - g_return_if_fail (container == GTK_CONTAINER (widget->parent)); - - - item_list = g_list_alloc (); - item_list->data = widget; - - gtk_list_remove_items (GTK_LIST (container), item_list); - - g_list_free (item_list); + gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECT_CHILD], child); } -static void -gtk_list_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) +void +gtk_list_unselect_child (GtkList *list, + GtkWidget *child) { - GtkList *list; - GtkWidget *child; - GList *children; + gtk_signal_emit (GTK_OBJECT (list), list_signals[UNSELECT_CHILD], child); +} - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_LIST (container)); - g_return_if_fail (callback != NULL); +void +gtk_list_select_all (GtkList *list) +{ + GtkContainer *container; + GList *work; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - list = GTK_LIST (container); - children = list->children; + if (!list->children) + return; + + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) + gtk_list_end_drag_selection (list); - while (children) + if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + gtk_list_end_selection (list); + + container = GTK_CONTAINER (list); + + switch (list->selection_mode) { - child = children->data; - children = children->next; + case GTK_SELECTION_BROWSE: + if (container->focus_child) + { + gtk_list_select_child (list, container->focus_child); + return; + } + break; - (* callback) (child, callback_data); + case GTK_SELECTION_EXTENDED: + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; + + if (list->children && + GTK_WIDGET_STATE (list->children->data) != GTK_STATE_SELECTED) + gtk_list_fake_toggle_row (list, GTK_WIDGET (list->children->data)); + + list->anchor_state = GTK_STATE_SELECTED; + list->anchor = 0; + list->drag_pos = 0; + list->undo_focus_child = container->focus_child; + gtk_list_update_extended_selection (list, g_list_length(list->children)); + gtk_list_end_selection (list); + return; + + case GTK_SELECTION_MULTIPLE: + for (work = list->children; work; work = work->next) + { + if (GTK_WIDGET_STATE (work->data) == GTK_STATE_NORMAL) + gtk_list_select_child (list, GTK_WIDGET (work->data)); + } + return; + + default: + break; } } -static void -gtk_real_list_select_child (GtkList *list, - GtkWidget *child) +void +gtk_list_unselect_all (GtkList *list) { - GList *selection; - GList *tmp_list; - GtkWidget *tmp_item; + GtkContainer *container; + GtkWidget *item; + GList *work; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + if (!list->children) + return; + + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) + gtk_list_end_drag_selection (list); + + if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + gtk_list_end_selection (list); - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); - g_return_if_fail (child != NULL); - g_return_if_fail (GTK_IS_LIST_ITEM (child)); + container = GTK_CONTAINER (list); switch (list->selection_mode) { - case GTK_SELECTION_SINGLE: case GTK_SELECTION_BROWSE: - selection = list->selection; - - while (selection) - { - tmp_item = selection->data; - - if (tmp_item != child) - { - tmp_list = selection; - selection = selection->next; - - list->selection = g_list_remove_link (list->selection, tmp_list); - g_list_free (tmp_list); - - gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item)); - gtk_widget_unref (GTK_WIDGET (tmp_item)); - } - else - selection = selection->next; - } - - if (child->state == GTK_STATE_NORMAL) + if (container->focus_child) { - list->selection = g_list_prepend (list->selection, child); - gtk_widget_ref (child); - gtk_list_item_select (GTK_LIST_ITEM (child)); + gtk_list_select_child (list, container->focus_child); + return; } - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); break; case GTK_SELECTION_EXTENDED: - if (list->anchor >= 0) - return; + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; - case GTK_SELECTION_MULTIPLE: - if (child->state == GTK_STATE_NORMAL) - { - list->selection = g_list_prepend (list->selection, child); - gtk_widget_ref (child); - gtk_list_item_select (GTK_LIST_ITEM (child)); - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); - } + list->anchor = -1; + list->drag_pos = -1; + list->undo_focus_child = container->focus_child; + break; + + default: break; } -} -static void -gtk_real_list_unselect_child (GtkList *list, - GtkWidget *child) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); - g_return_if_fail (child != NULL); - g_return_if_fail (GTK_IS_LIST_ITEM (child)); + work = list->selection; - if (child->state == GTK_STATE_SELECTED) + while (work) { - list->selection = g_list_remove (list->selection, child); - gtk_list_item_deselect (GTK_LIST_ITEM (child)); - gtk_widget_unref (child); - gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); + item = work->data; + work = work->next; + gtk_list_unselect_child (list, item); } } - -/***************************************************************************/ - -static void -gtk_list_set_anchor (GtkList *list, - gboolean add_mode, - gint anchor, - GtkWidget *undo_focus_child) +void +gtk_list_extend_selection (GtkList *list, + GtkScrollType scroll_type, + gfloat position, + gboolean auto_start_selection) { - GList *work; + GtkContainer *container; g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - - if (list->selection_mode != GTK_SELECTION_EXTENDED || list->anchor >= 0) + + if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || + list->selection_mode != GTK_SELECTION_EXTENDED) return; - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; + container = GTK_CONTAINER (list); - if ((work = g_list_nth (list->children, anchor))) + if (auto_start_selection) { - if (add_mode) - gtk_list_fake_toggle_row (list, GTK_WIDGET (work->data)); - else - { - gtk_list_fake_unselect_all (list, GTK_WIDGET (work->data)); - list->anchor_state = GTK_STATE_SELECTED; - } + gint focus_row; + + focus_row = g_list_index (list->children, container->focus_child); + gtk_list_set_anchor (list, list->add_mode, focus_row, + container->focus_child); } + else if (list->anchor < 0) + return; - list->anchor = anchor; - list->drag_pos = anchor; - list->undo_focus_child = undo_focus_child; + gtk_list_move_focus_child (list, scroll_type, position); + gtk_list_update_extended_selection + (list, g_list_index (list->children, container->focus_child)); } -static void -gtk_list_fake_unselect_all (GtkList *list, - GtkWidget *item) +void +gtk_list_end_drag_selection (GtkList *list) { - GList *work; - - if (item && item->state == GTK_STATE_NORMAL) - gtk_widget_set_state (item, GTK_STATE_SELECTED); - - list->undo_selection = list->selection; - list->selection = NULL; - - for (work = list->undo_selection; work; work = work->next) - if (work->data != item) - gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL); -} + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); -static void -gtk_list_fake_toggle_row (GtkList *list, - GtkWidget *item) -{ - if (!item) - return; - - if (item->state == GTK_STATE_NORMAL) + list->drag_selection = FALSE; + if (GTK_WIDGET_HAS_GRAB (list)) { - list->anchor_state = GTK_STATE_SELECTED; - gtk_widget_set_state (item, GTK_STATE_SELECTED); + gtk_grab_remove (GTK_WIDGET (list)); + gdk_pointer_ungrab (GDK_CURRENT_TIME); } - else + if (list->htimer) { - list->anchor_state = GTK_STATE_NORMAL; - gtk_widget_set_state (item, GTK_STATE_NORMAL); + gtk_timeout_remove (list->htimer); + list->htimer = 0; + } + if (list->vtimer) + { + gtk_timeout_remove (list->vtimer); + list->vtimer = 0; } } void -gtk_list_scroll_horizontal (GtkList *list, - GtkScrollType scroll_type, - gfloat position) +gtk_list_start_selection (GtkList *list) { - GtkAdjustment *adj; + GtkContainer *container; + gint focus_row; - g_return_if_fail (list != 0); + g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) return; - if (!(adj = - gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id))) + container = GTK_CONTAINER (list); + + if ((focus_row = g_list_index (list->selection, container->focus_child)) + >= 0) + gtk_list_set_anchor (list, list->add_mode, + focus_row, container->focus_child); +} + +void +gtk_list_end_selection (GtkList *list) +{ + gint i; + gint e; + GList *work; + GtkWidget *item; + gint item_index; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || + list->anchor < 0) return; - switch (scroll_type) + i = MIN (list->anchor, list->drag_pos); + e = MAX (list->anchor, list->drag_pos); + + list->anchor = -1; + list->drag_pos = -1; + + if (list->undo_selection) { - case GTK_SCROLL_STEP_BACKWARD: - adj->value = CLAMP (adj->value - adj->step_increment, adj->lower, - adj->upper - adj->page_size); - break; - case GTK_SCROLL_STEP_FORWARD: - adj->value = CLAMP (adj->value + adj->step_increment, adj->lower, - adj->upper - adj->page_size); - break; - case GTK_SCROLL_PAGE_BACKWARD: - adj->value = CLAMP (adj->value - adj->page_increment, adj->lower, - adj->upper - adj->page_size); - break; - case GTK_SCROLL_PAGE_FORWARD: - adj->value = CLAMP (adj->value + adj->page_increment, adj->lower, - adj->upper - adj->page_size); - break; - case GTK_SCROLL_JUMP: - adj->value = CLAMP (adj->lower + (adj->upper - adj->lower) * position, - adj->lower, adj->upper - adj->page_size); - break; - default: - break; + work = list->selection; + list->selection = list->undo_selection; + list->undo_selection = work; + work = list->selection; + while (work) + { + item = work->data; + work = work->next; + item_index = g_list_index (list->children, item); + if (item_index < i || item_index > e) + { + gtk_widget_set_state (item, GTK_STATE_SELECTED); + gtk_list_unselect_child (list, item); + list->undo_selection = g_list_prepend (list->undo_selection, + item); + } + } + } + + for (work = g_list_nth (list->children, i); i <= e; i++, work = work->next) + { + item = work->data; + if (g_list_find (list->selection, item)) + { + if (item->state == GTK_STATE_NORMAL) + { + gtk_widget_set_state (item, GTK_STATE_SELECTED); + gtk_list_unselect_child (list, item); + list->undo_selection = g_list_prepend (list->undo_selection, + item); + } + } + else if (item->state == GTK_STATE_SELECTED) + { + gtk_widget_set_state (item, GTK_STATE_NORMAL); + list->undo_unselection = g_list_prepend (list->undo_unselection, + item); + } } - gtk_adjustment_value_changed (adj); + + for (work = list->undo_unselection; work; work = work->next) + gtk_list_select_child (list, GTK_WIDGET (work->data)); + } -void -gtk_list_scroll_vertical (GtkList *list, - GtkScrollType scroll_type, - gfloat position) +void +gtk_list_toggle_row (GtkList *list, + GtkWidget *item) { g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); + g_return_if_fail (item != NULL); + g_return_if_fail (GTK_IS_LIST_ITEM (item)); - if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) - return; - - if (list->selection_mode == GTK_SELECTION_EXTENDED) + switch (list->selection_mode) { - GtkContainer *container; - - if (list->anchor >= 0) - return; + case GTK_SELECTION_EXTENDED: + case GTK_SELECTION_MULTIPLE: + case GTK_SELECTION_SINGLE: - container = GTK_CONTAINER (list); - list->undo_focus_child = container->focus_child; - gtk_list_move_focus_child (list, scroll_type, position); - if (container->focus_child != list->undo_focus_child && !list->add_mode) + if (item->state == GTK_STATE_SELECTED) { - gtk_list_unselect_all (list); - gtk_list_select_child (list, container->focus_child); + gtk_list_unselect_child (list, item); + return; } + + case GTK_SELECTION_BROWSE: + gtk_list_select_child (list, item); + break; } - else - gtk_list_move_focus_child (list, scroll_type, position); } -static void -gtk_list_move_focus_child (GtkList *list, - GtkScrollType scroll_type, - gfloat position) +void +gtk_list_toggle_focus_row (GtkList *list) { GtkContainer *container; - GList *work; - GtkWidget *item; - GtkAdjustment *adj; - gint new_value; + gint focus_row; g_return_if_fail (list != 0); g_return_if_fail (GTK_IS_LIST (list)); container = GTK_CONTAINER (list); - if (container->focus_child) - work = g_list_find (list->children, container->focus_child); - else - work = list->children; - - if (!work) + if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || + !container->focus_child) return; - switch (scroll_type) + switch (list->selection_mode) { - case GTK_SCROLL_STEP_BACKWARD: - work = work->prev; - if (work) - gtk_widget_grab_focus (GTK_WIDGET (work->data)); - break; - - case GTK_SCROLL_STEP_FORWARD: - work = work->next; - if (work) - gtk_widget_grab_focus (GTK_WIDGET (work->data)); + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: + + gtk_list_toggle_row (list, container->focus_child); break; + + case GTK_SELECTION_EXTENDED: - case GTK_SCROLL_PAGE_BACKWARD: - if (!work->prev) - return; - - item = work->data; - adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id); - - if (adj) - { - gboolean correct = FALSE; - - new_value = adj->value; - - if (item->allocation.y <= adj->value) - { - new_value = MAX (item->allocation.y + item->allocation.height - - adj->page_size, adj->lower); - correct = TRUE; - } - - if (item->allocation.y > new_value) - for (; work; work = work->prev) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y <= new_value && - item->allocation.y + item->allocation.height > new_value) - break; - } - else - for (; work; work = work->next) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y <= new_value && - item->allocation.y + item->allocation.height > new_value) - break; - } - - if (correct && work && work->next && item->allocation.y < new_value) - item = work->next->data; - } - else - item = list->children->data; - - gtk_widget_grab_focus (item); - break; - - case GTK_SCROLL_PAGE_FORWARD: - if (!work->next) + if ((focus_row = g_list_index (list->children, container->focus_child)) + < 0) return; - item = work->data; - adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id); - - if (adj) - { - gboolean correct = FALSE; - - new_value = adj->value; - - if (item->allocation.y + item->allocation.height >= - adj->value + adj->page_size) - { - new_value = item->allocation.y; - correct = TRUE; - } - - new_value = MIN (new_value + adj->page_size, adj->upper); + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; - if (item->allocation.y > new_value) - for (; work; work = work->prev) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y <= new_value && - item->allocation.y + item->allocation.height > new_value) - break; - } - else - for (; work; work = work->next) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y <= new_value && - item->allocation.y + item->allocation.height > new_value) - break; - } + list->anchor = focus_row; + list->drag_pos = focus_row; + list->undo_focus_child = container->focus_child; - if (correct && work && work->prev && - item->allocation.y + item->allocation.height - 1 > new_value) - item = work->prev->data; - } + if (list->add_mode) + gtk_list_fake_toggle_row (list, container->focus_child); else - item = g_list_last (work)->data; - - gtk_widget_grab_focus (item); - break; - - case GTK_SCROLL_JUMP: - new_value = GTK_WIDGET(list)->allocation.height * CLAMP (position, 0, 1); - - for (item = NULL, work = list->children; work; work =work->next) - { - item = GTK_WIDGET (work->data); - if (item->allocation.y <= new_value && - item->allocation.y + item->allocation.height > new_value) - break; - } - - gtk_widget_grab_focus (item); + gtk_list_fake_unselect_all (list, container->focus_child); + + gtk_list_end_selection (list); break; - + default: break; } } void -gtk_list_select_all (GtkList *list) +gtk_list_toggle_add_mode (GtkList *list) { GtkContainer *container; - GList *work; - - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); - if (!list->children) + g_return_if_fail (list != 0); + g_return_if_fail (GTK_IS_LIST (list)); + + if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || + list->selection_mode != GTK_SELECTION_EXTENDED) return; - if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) - gtk_list_end_drag_selection (list); - - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) - gtk_list_end_selection (list); - container = GTK_CONTAINER (list); - switch (list->selection_mode) + if (list->add_mode) { - case GTK_SELECTION_BROWSE: - if (container->focus_child) - { - gtk_list_select_child (list, container->focus_child); - return; - } - break; - - case GTK_SELECTION_EXTENDED: - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; - - if (list->children && - GTK_WIDGET_STATE (list->children->data) != GTK_STATE_SELECTED) - gtk_list_fake_toggle_row (list, GTK_WIDGET (list->children->data)); - - list->anchor_state = GTK_STATE_SELECTED; - list->anchor = 0; - list->drag_pos = 0; - list->undo_focus_child = container->focus_child; - gtk_list_update_extended_selection (list, g_list_length(list->children)); - gtk_list_end_selection (list); - return; - - case GTK_SELECTION_MULTIPLE: - for (work = list->children; work; work = work->next) - { - if (GTK_WIDGET_STATE (work->data) == GTK_STATE_NORMAL) - gtk_list_select_child (list, GTK_WIDGET (work->data)); - } - return; - - default: - break; + list->add_mode = FALSE; + list->anchor_state = GTK_STATE_SELECTED; } + else + list->add_mode = TRUE; + + if (container->focus_child) + gtk_widget_queue_draw (container->focus_child); } void -gtk_list_unselect_all (GtkList *list) +gtk_list_undo_selection (GtkList *list) { - GtkContainer *container; - GtkWidget *item; GList *work; - + g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - if (!list->children) + if (list->selection_mode != GTK_SELECTION_EXTENDED || + (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))) return; - if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) - gtk_list_end_drag_selection (list); - - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) + if (list->anchor >= 0) gtk_list_end_selection (list); - container = GTK_CONTAINER (list); + if (!(list->undo_selection || list->undo_unselection)) + { + gtk_list_unselect_all (list); + return; + } - switch (list->selection_mode) + for (work = list->undo_selection; work; work = work->next) + gtk_list_select_child (list, GTK_WIDGET (work->data)); + + for (work = list->undo_unselection; work; work = work->next) + gtk_list_unselect_child (list, GTK_WIDGET (work->data)); + + if (list->undo_focus_child) { - case GTK_SELECTION_BROWSE: - if (container->focus_child) - { - gtk_list_select_child (list, container->focus_child); - return; - } - break; + GtkContainer *container; - case GTK_SELECTION_EXTENDED: - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; + container = GTK_CONTAINER (list); - list->anchor = -1; - list->drag_pos = -1; - list->undo_focus_child = container->focus_child; - break; + if (container->focus_child && + GTK_WIDGET_HAS_FOCUS (container->focus_child)) + gtk_widget_grab_focus (list->undo_focus_child); + else + gtk_container_set_focus_child (container, list->undo_focus_child); + } + + list->undo_focus_child = NULL; + + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; +} + + +/* Private GtkList Selection Methods : + * + * gtk_real_list_select_child + * gtk_real_list_unselect_child + */ +static void +gtk_real_list_select_child (GtkList *list, + GtkWidget *child) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_IS_LIST_ITEM (child)); + switch (child->state) + { + case GTK_STATE_SELECTED: + case GTK_STATE_INSENSITIVE: + break; default: + gtk_list_item_select (GTK_LIST_ITEM (child)); break; } +} - work = list->selection; +static void +gtk_real_list_unselect_child (GtkList *list, + GtkWidget *child) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_IS_LIST_ITEM (child)); - while (work) - { - item = work->data; - work = work->next; - gtk_list_unselect_child (list, item); - } + if (child->state == GTK_STATE_SELECTED) + gtk_list_item_deselect (GTK_LIST_ITEM (child)); } -void -gtk_list_extend_selection (GtkList *list, - GtkScrollType scroll_type, - gfloat position, - gboolean auto_start_selection) + +/* Private GtkList Selection Functions : + * + * gtk_list_set_anchor + * gtk_list_fake_unselect_all + * gtk_list_fake_toggle_row + * gtk_list_update_extended_selection + */ +static void +gtk_list_set_anchor (GtkList *list, + gboolean add_mode, + gint anchor, + GtkWidget *undo_focus_child) { - GtkContainer *container; + GList *work; g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || - list->selection_mode != GTK_SELECTION_EXTENDED) + + if (list->selection_mode != GTK_SELECTION_EXTENDED || list->anchor >= 0) return; - container = GTK_CONTAINER (list); + g_list_free (list->undo_selection); + g_list_free (list->undo_unselection); + list->undo_selection = NULL; + list->undo_unselection = NULL; - if (auto_start_selection) + if ((work = g_list_nth (list->children, anchor))) { - gint focus_row; - focus_row = g_list_index (list->children, container->focus_child); - gtk_list_set_anchor (list, list->add_mode, focus_row, - container->focus_child); + if (add_mode) + gtk_list_fake_toggle_row (list, GTK_WIDGET (work->data)); + else + { + gtk_list_fake_unselect_all (list, GTK_WIDGET (work->data)); + list->anchor_state = GTK_STATE_SELECTED; + } } - else if (list->anchor < 0) - return; - gtk_list_move_focus_child (list, scroll_type, position); - gtk_list_update_extended_selection - (list, g_list_index (list->children, container->focus_child)); + list->anchor = anchor; + list->drag_pos = anchor; + list->undo_focus_child = undo_focus_child; +} + +static void +gtk_list_fake_unselect_all (GtkList *list, + GtkWidget *item) +{ + GList *work; + + if (item && item->state == GTK_STATE_NORMAL) + gtk_widget_set_state (item, GTK_STATE_SELECTED); + + list->undo_selection = list->selection; + list->selection = NULL; + + for (work = list->undo_selection; work; work = work->next) + if (work->data != item) + gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL); +} + +static void +gtk_list_fake_toggle_row (GtkList *list, + GtkWidget *item) +{ + if (!item) + return; + + if (item->state == GTK_STATE_NORMAL) + { + list->anchor_state = GTK_STATE_SELECTED; + gtk_widget_set_state (item, GTK_STATE_SELECTED); + } + else + { + list->anchor_state = GTK_STATE_NORMAL; + gtk_widget_set_state (item, GTK_STATE_NORMAL); + } } static void @@ -1912,362 +2025,575 @@ gtk_list_update_extended_selection (GtkList *list, list->drag_pos = row; - /* restore the elements between s1 and e1 */ - if (s1 >= 0) - { - for (i = s1, work = g_list_nth (list->children, i); i <= e1; - i++, work = work->next) + /* restore the elements between s1 and e1 */ + if (s1 >= 0) + { + for (i = s1, work = g_list_nth (list->children, i); i <= e1; + i++, work = work->next) + { + if (g_list_find (list->selection, work->data)) + gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_SELECTED); + else + gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL); + } + } + + /* extend the selection between s2 and e2 */ + if (s2 >= 0) + { + for (i = s2, work = g_list_nth (list->children, i); i <= e2; + i++, work = work->next) + if (GTK_WIDGET (work->data)->state != list->anchor_state) + gtk_widget_set_state (GTK_WIDGET (work->data), list->anchor_state); + } +} + + +/* Public GtkList Scroll Methods : + * + * gtk_list_scroll_horizontal + * gtk_list_scroll_vertical + */ +void +gtk_list_scroll_horizontal (GtkList *list, + GtkScrollType scroll_type, + gfloat position) +{ + GtkAdjustment *adj; + + g_return_if_fail (list != 0); + g_return_if_fail (GTK_IS_LIST (list)); + + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) + return; + + if (!(adj = + gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id))) + return; + + switch (scroll_type) + { + case GTK_SCROLL_STEP_BACKWARD: + adj->value = CLAMP (adj->value - adj->step_increment, adj->lower, + adj->upper - adj->page_size); + break; + case GTK_SCROLL_STEP_FORWARD: + adj->value = CLAMP (adj->value + adj->step_increment, adj->lower, + adj->upper - adj->page_size); + break; + case GTK_SCROLL_PAGE_BACKWARD: + adj->value = CLAMP (adj->value - adj->page_increment, adj->lower, + adj->upper - adj->page_size); + break; + case GTK_SCROLL_PAGE_FORWARD: + adj->value = CLAMP (adj->value + adj->page_increment, adj->lower, + adj->upper - adj->page_size); + break; + case GTK_SCROLL_JUMP: + adj->value = CLAMP (adj->lower + (adj->upper - adj->lower) * position, + adj->lower, adj->upper - adj->page_size); + break; + default: + break; + } + gtk_adjustment_value_changed (adj); +} + +void +gtk_list_scroll_vertical (GtkList *list, + GtkScrollType scroll_type, + gfloat position) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); + + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) + return; + + if (list->selection_mode == GTK_SELECTION_EXTENDED) + { + GtkContainer *container; + + if (list->anchor >= 0) + return; + + container = GTK_CONTAINER (list); + list->undo_focus_child = container->focus_child; + gtk_list_move_focus_child (list, scroll_type, position); + if (container->focus_child != list->undo_focus_child && !list->add_mode) { - if (g_list_find (list->selection, work->data)) - gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_SELECTED); - else - gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL); + gtk_list_unselect_all (list); + gtk_list_select_child (list, container->focus_child); } } - - /* extend the selection between s2 and e2 */ - if (s2 >= 0) - { - for (i = s2, work = g_list_nth (list->children, i); i <= e2; - i++, work = work->next) - if (GTK_WIDGET (work->data)->state != list->anchor_state) - gtk_widget_set_state (GTK_WIDGET (work->data), list->anchor_state); - } + else + gtk_list_move_focus_child (list, scroll_type, position); } -void -gtk_list_end_selection (GtkList *list) + +/* Private GtkList Scroll/Focus Functions : + * + * gtk_list_move_focus_child + * gtk_list_horizontal_timeout + * gtk_list_vertical_timeout + */ +static void +gtk_list_move_focus_child (GtkList *list, + GtkScrollType scroll_type, + gfloat position) { - gint i; - gint e; + GtkContainer *container; GList *work; GtkWidget *item; - gint item_index; + GtkAdjustment *adj; + gint new_value; - g_return_if_fail (list != NULL); + g_return_if_fail (list != 0); g_return_if_fail (GTK_IS_LIST (list)); - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || - list->anchor < 0) - return; + container = GTK_CONTAINER (list); - i = MIN (list->anchor, list->drag_pos); - e = MAX (list->anchor, list->drag_pos); - - list->anchor = -1; - list->drag_pos = -1; + if (container->focus_child) + work = g_list_find (list->children, container->focus_child); + else + work = list->children; - if (list->undo_selection) + if (!work) + return; + + switch (scroll_type) { - work = list->selection; - list->selection = list->undo_selection; - list->undo_selection = work; - work = list->selection; - while (work) + case GTK_SCROLL_STEP_BACKWARD: + work = work->prev; + if (work) + gtk_widget_grab_focus (GTK_WIDGET (work->data)); + break; + + case GTK_SCROLL_STEP_FORWARD: + work = work->next; + if (work) + gtk_widget_grab_focus (GTK_WIDGET (work->data)); + break; + + case GTK_SCROLL_PAGE_BACKWARD: + if (!work->prev) + return; + + item = work->data; + adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id); + + if (adj) { - item = work->data; - work = work->next; - item_index = g_list_index (list->children, item); - if (item_index < i || item_index > e) + gboolean correct = FALSE; + + new_value = adj->value; + + if (item->allocation.y <= adj->value) { - gtk_widget_set_state (item, GTK_STATE_SELECTED); - gtk_list_unselect_child (list, item); - list->undo_selection = g_list_prepend (list->undo_selection, - item); + new_value = MAX (item->allocation.y + item->allocation.height + - adj->page_size, adj->lower); + correct = TRUE; } + + if (item->allocation.y > new_value) + for (; work; work = work->prev) + { + item = GTK_WIDGET (work->data); + if (item->allocation.y <= new_value && + item->allocation.y + item->allocation.height > new_value) + break; + } + else + for (; work; work = work->next) + { + item = GTK_WIDGET (work->data); + if (item->allocation.y <= new_value && + item->allocation.y + item->allocation.height > new_value) + break; + } + + if (correct && work && work->next && item->allocation.y < new_value) + item = work->next->data; } - } + else + item = list->children->data; + + gtk_widget_grab_focus (item); + break; + + case GTK_SCROLL_PAGE_FORWARD: + if (!work->next) + return; - for (work = g_list_nth (list->children, i); i <= e; i++, work = work->next) - { item = work->data; - if (g_list_find (list->selection, item)) - { - if (item->state == GTK_STATE_NORMAL) + adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id); + + if (adj) + { + gboolean correct = FALSE; + + new_value = adj->value; + + if (item->allocation.y + item->allocation.height >= + adj->value + adj->page_size) + { + new_value = item->allocation.y; + correct = TRUE; + } + + new_value = MIN (new_value + adj->page_size, adj->upper); + + if (item->allocation.y > new_value) + for (; work; work = work->prev) { - gtk_widget_set_state (item, GTK_STATE_SELECTED); - gtk_list_unselect_child (list, item); - list->undo_selection = g_list_prepend (list->undo_selection, - item); + item = GTK_WIDGET (work->data); + if (item->allocation.y <= new_value && + item->allocation.y + item->allocation.height > new_value) + break; } - } - else if (item->state == GTK_STATE_SELECTED) + else + for (; work; work = work->next) + { + item = GTK_WIDGET (work->data); + if (item->allocation.y <= new_value && + item->allocation.y + item->allocation.height > new_value) + break; + } + + if (correct && work && work->prev && + item->allocation.y + item->allocation.height - 1 > new_value) + item = work->prev->data; + } + else + item = g_list_last (work)->data; + + gtk_widget_grab_focus (item); + break; + + case GTK_SCROLL_JUMP: + new_value = GTK_WIDGET(list)->allocation.height * CLAMP (position, 0, 1); + + for (item = NULL, work = list->children; work; work =work->next) { - gtk_widget_set_state (item, GTK_STATE_NORMAL); - list->undo_unselection = g_list_prepend (list->undo_unselection, - item); + item = GTK_WIDGET (work->data); + if (item->allocation.y <= new_value && + item->allocation.y + item->allocation.height > new_value) + break; } + + gtk_widget_grab_focus (item); + break; + + default: + break; } +} - for (work = list->undo_unselection; work; work = work->next) - gtk_list_select_child (list, GTK_WIDGET (work->data)); +static gint +gtk_list_horizontal_timeout (GtkWidget *list) +{ + gint x, y; + GdkEventMotion event; + GdkModifierType mask; + + g_return_val_if_fail (GTK_IS_LIST (list), FALSE); + + GTK_LIST (list)->htimer = 0; + gdk_window_get_pointer (list->window, &x, &y, &mask); + + event.is_hint = 0; + event.x = x; + event.y = y; + event.state = mask; + gtk_list_motion_notify (list, &event); + + return FALSE; } -void -gtk_list_start_selection (GtkList *list) +static gint +gtk_list_vertical_timeout (GtkWidget *list) { - GtkContainer *container; - gint focus_row; + gint x; + gint y; + GdkEventMotion event; + GdkModifierType mask; - g_return_if_fail (list != NULL); - g_return_if_fail (GTK_IS_LIST (list)); + g_return_val_if_fail (GTK_IS_LIST (list), FALSE); - if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) - return; + GTK_LIST (list)->vtimer = 0; + gdk_window_get_pointer (list->window, &x, &y, &mask); - container = GTK_CONTAINER (list); + event.is_hint = 0; + event.x = x; + event.y = y; + event.state = mask; - if ((focus_row = g_list_index (list->selection, container->focus_child)) - >= 0) - gtk_list_set_anchor (list, list->add_mode, - focus_row, container->focus_child); + gtk_list_motion_notify (list, &event); + + return FALSE; } -void -gtk_list_toggle_row (GtkList *list, - GtkWidget *item) + +/* Private GtkListItem Signal Functions : + * + * gtk_list_signal_focus_lost + * gtk_list_signal_toggle_focus_row + * gtk_list_signal_select_all + * gtk_list_signal_unselect_all + * gtk_list_signal_undo_selection + * gtk_list_signal_start_selection + * gtk_list_signal_end_selection + * gtk_list_signal_extend_selection + * gtk_list_signal_scroll_horizontal + * gtk_list_signal_scroll_vertical + * gtk_list_signal_toggle_add_mode + * gtk_list_signal_item_select + * gtk_list_signal_item_deselect + * gtk_list_signal_item_toggle + */ +static void +gtk_list_signal_focus_lost (GtkWidget *item, + GdkEventKey *event, + GtkList *list) { g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); g_return_if_fail (item != NULL); g_return_if_fail (GTK_IS_LIST_ITEM (item)); - switch (list->selection_mode) - { - case GTK_SELECTION_EXTENDED: - case GTK_SELECTION_MULTIPLE: - case GTK_SELECTION_SINGLE: - - if (item->state == GTK_STATE_SELECTED) - { - gtk_list_unselect_child (list, item); - return; - } - - case GTK_SELECTION_BROWSE: - gtk_list_select_child (list, item); - break; - } + if (list->selection_mode == GTK_SELECTION_EXTENDED && + list->anchor >= 0 && + item == GTK_CONTAINER (list)->focus_child) + gtk_list_end_selection (list); } -void -gtk_list_toggle_focus_row (GtkList *list) +static void +gtk_list_signal_toggle_focus_row (GtkListItem *list_item, + GtkList *list) { - GtkContainer *container; - gint focus_row; - - g_return_if_fail (list != 0); + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - container = GTK_CONTAINER (list); + gtk_list_toggle_focus_row (list); +} - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || - !container->focus_child) - return; +static void +gtk_list_signal_select_all (GtkListItem *list_item, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - switch (list->selection_mode) - { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: - - gtk_list_toggle_row (list, container->focus_child); - break; - - case GTK_SELECTION_EXTENDED: + gtk_list_select_all (list); +} - if ((focus_row = g_list_index (list->children, container->focus_child)) - < 0) - return; +static void +gtk_list_signal_unselect_all (GtkListItem *list_item, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; + gtk_list_unselect_all (list); +} - list->anchor = focus_row; - list->drag_pos = focus_row; - list->undo_focus_child = container->focus_child; +static void +gtk_list_signal_undo_selection (GtkListItem *list_item, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - if (list->add_mode) - gtk_list_fake_toggle_row (list, container->focus_child); - else - gtk_list_fake_unselect_all (list, container->focus_child); - - gtk_list_end_selection (list); - break; - - default: - break; - } + gtk_list_undo_selection (list); } -void -gtk_list_toggle_add_mode (GtkList *list) +static void +gtk_list_signal_start_selection (GtkListItem *list_item, + GtkList *list) { - GtkContainer *container; - - g_return_if_fail (list != 0); + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) || - list->selection_mode != GTK_SELECTION_EXTENDED) - return; - - container = GTK_CONTAINER (list); - if (list->add_mode) - { - list->add_mode = FALSE; - list->anchor_state = GTK_STATE_SELECTED; - } - else - list->add_mode = TRUE; - - if (container->focus_child) - gtk_widget_queue_draw (container->focus_child); + gtk_list_start_selection (list); } -void -gtk_list_undo_selection (GtkList *list) +static void +gtk_list_signal_end_selection (GtkListItem *list_item, + GtkList *list) { - GList *work; - + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - if (list->selection_mode != GTK_SELECTION_EXTENDED || - (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))) - return; - - if (list->anchor >= 0) - gtk_list_end_selection (list); - - if (!(list->undo_selection || list->undo_unselection)) - { - gtk_list_unselect_all (list); - return; - } + gtk_list_end_selection (list); +} - for (work = list->undo_selection; work; work = work->next) - gtk_list_select_child (list, GTK_WIDGET (work->data)); +static void +gtk_list_signal_extend_selection (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + gboolean auto_start_selection, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - for (work = list->undo_unselection; work; work = work->next) - gtk_list_unselect_child (list, GTK_WIDGET (work->data)); + gtk_list_extend_selection (list, scroll_type, position, + auto_start_selection); +} - if (list->undo_focus_child) - { - GtkContainer *container; +static void +gtk_list_signal_scroll_horizontal (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - container = GTK_CONTAINER (list); + gtk_list_scroll_horizontal (list, scroll_type, position); +} - if (container->focus_child && - GTK_WIDGET_HAS_FOCUS (container->focus_child)) - gtk_widget_grab_focus (list->undo_focus_child); - else - gtk_container_set_focus_child (container, list->undo_focus_child); - } +static void +gtk_list_signal_scroll_vertical (GtkListItem *list_item, + GtkScrollType scroll_type, + gfloat position, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - list->undo_focus_child = NULL; - - g_list_free (list->undo_selection); - g_list_free (list->undo_unselection); - list->undo_selection = NULL; - list->undo_unselection = NULL; + gtk_list_scroll_vertical (list, scroll_type, position); } static void -gtk_list_focus_lost (GtkWidget *item, - GdkEventKey *event, - GtkList *list) +gtk_list_signal_toggle_add_mode (GtkListItem *list_item, + GtkList *list) { + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); g_return_if_fail (list != NULL); g_return_if_fail (GTK_IS_LIST (list)); - g_return_if_fail (item != NULL); - g_return_if_fail (GTK_IS_LIST_ITEM (item)); - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0 && - item == GTK_CONTAINER (list)->focus_child) - gtk_list_end_selection (list); + gtk_list_toggle_add_mode (list); } static void -gtk_list_set_focus_child (GtkContainer *container, - GtkWidget *child) +gtk_list_signal_item_select (GtkListItem *list_item, + GtkList *list) { - GtkList *list; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_LIST (container)); + GList *selection; + GList *tmp_list; + GList *sel_list; - if (child) - g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - list = GTK_LIST (container); - list->last_focus_child = container->focus_child; + if (GTK_WIDGET (list_item)->state != GTK_STATE_SELECTED) + return; - if (child != container->focus_child) + switch (list->selection_mode) { - if (container->focus_child) - gtk_widget_unref (container->focus_child); - container->focus_child = child; - if (container->focus_child) - gtk_widget_ref (container->focus_child); - } + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_BROWSE: + sel_list = NULL; + selection = list->selection; - /* check for v adjustment */ - if (container->focus_child) - { - GtkAdjustment *adjustment; + while (selection) + { + tmp_list = selection; + selection = selection->next; - adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), - vadjustment_key_id); - if (adjustment) - gtk_adjustment_clamp_page (adjustment, - container->focus_child->allocation.y, - (container->focus_child->allocation.y + - container->focus_child->allocation.height)); - } + if (tmp_list->data == list_item) + sel_list = tmp_list; + else + gtk_list_item_deselect (GTK_LIST_ITEM (tmp_list->data)); + } - switch (list->selection_mode) - { - case GTK_SELECTION_BROWSE: - if (child) - gtk_list_select_child (list, child); + if (!sel_list) + { + list->selection = g_list_prepend (list->selection, list_item); + gtk_widget_ref (GTK_WIDGET (list_item)); + } + gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); break; - default: + case GTK_SELECTION_EXTENDED: + if (list->anchor >= 0) + return; + case GTK_SELECTION_MULTIPLE: + if (!g_list_find (list->selection, list_item)) + { + list->selection = g_list_prepend (list->selection, list_item); + gtk_widget_ref (GTK_WIDGET (list_item)); + gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); + } break; } } - -static gint -gtk_list_focus (GtkContainer *container, - GtkDirectionType direction) +static void +gtk_list_signal_item_deselect (GtkListItem *list_item, + GtkList *list) { - gint return_val = FALSE; + GList *node; - g_return_val_if_fail (container != NULL, FALSE); - g_return_val_if_fail (GTK_IS_LIST (container), FALSE); + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - if (!GTK_WIDGET_SENSITIVE (container)) - return_val = FALSE; - else if (container->focus_child == NULL || - !GTK_WIDGET_HAS_FOCUS (container->focus_child)) + if (GTK_WIDGET (list_item)->state != GTK_STATE_NORMAL) + return; + + node = g_list_find (list->selection, list_item); + + if (node) { - if (*GTK_CONTAINER_CLASS (parent_class)->focus) - return_val = GTK_CONTAINER_CLASS (parent_class)->focus - (container, direction); + list->selection = g_list_remove_link (list->selection, node); + g_list_free_1 (node); + gtk_widget_unref (GTK_WIDGET (list_item)); + gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]); } - - if (!return_val) - { - GtkList *list; +} - list = GTK_LIST (container); - if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0) - gtk_list_end_selection (list); - } +static void +gtk_list_signal_item_toggle (GtkListItem *list_item, + GtkList *list) +{ + g_return_if_fail (list_item != 0); + g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_LIST (list)); - return return_val; + switch (GTK_WIDGET (list_item)->state) + { + case GTK_STATE_SELECTED: + gtk_list_signal_item_select (list_item, list); + break; + case GTK_STATE_NORMAL: + gtk_list_signal_item_deselect (list_item, list); + break; + default: + break; + } } diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c index d81ad37194..bab73bd2c3 100644 --- a/gtk/gtklistitem.c +++ b/gtk/gtklistitem.c @@ -63,24 +63,6 @@ static void gtk_real_list_item_deselect (GtkItem *item); static void gtk_real_list_item_toggle (GtkItem *item); -static void gtk_list_item_toggle_focus_row (GtkListItem *list_item); -static void gtk_list_item_select_all (GtkListItem *list_item); -static void gtk_list_item_unselect_all (GtkListItem *list_item); -static void gtk_list_item_undo_selection (GtkListItem *list_item); -static void gtk_list_item_start_selection (GtkListItem *list_item); -static void gtk_list_item_end_selection (GtkListItem *list_item); -static void gtk_list_item_extend_selection (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position, - gboolean auto_start_selection); -static void gtk_list_item_scroll_horizontal (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position); -static void gtk_list_item_scroll_vertical (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position); -static void gtk_list_item_toggle_add_mode (GtkListItem *list_item); - static GtkItemClass *parent_class = NULL; static guint list_item_signals[LAST_SIGNAL] = {0}; @@ -195,6 +177,7 @@ gtk_list_item_class_init (GtkListItemClass *class) gtk_marshal_NONE__ENUM_FLOAT, GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_FLOAT); + gtk_object_class_add_signals (object_class, list_item_signals, LAST_SIGNAL); widget_class->realize = gtk_list_item_realize; widget_class->size_request = gtk_list_item_size_request; @@ -210,16 +193,16 @@ gtk_list_item_class_init (GtkListItemClass *class) item_class->deselect = gtk_real_list_item_deselect; item_class->toggle = gtk_real_list_item_toggle; - class->toggle_focus_row = gtk_list_item_toggle_focus_row; - class->select_all = gtk_list_item_select_all; - class->unselect_all = gtk_list_item_unselect_all; - class->undo_selection = gtk_list_item_undo_selection; - class->start_selection = gtk_list_item_start_selection; - class->end_selection = gtk_list_item_end_selection; - class->extend_selection = gtk_list_item_extend_selection; - class->scroll_horizontal = gtk_list_item_scroll_horizontal; - class->scroll_vertical = gtk_list_item_scroll_vertical; - class->toggle_add_mode = gtk_list_item_toggle_add_mode; + class->toggle_focus_row = NULL; + class->select_all = NULL; + class->unselect_all = NULL; + class->undo_selection = NULL; + class->start_selection = NULL; + class->end_selection = NULL; + class->extend_selection = NULL; + class->scroll_horizontal = NULL; + class->scroll_vertical = NULL; + class->toggle_add_mode = NULL; { GtkBindingSet *binding_set; @@ -619,7 +602,15 @@ gtk_real_list_item_select (GtkItem *item) g_return_if_fail (item != NULL); g_return_if_fail (GTK_IS_LIST_ITEM (item)); - gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED); + switch (GTK_WIDGET (item)->state) + { + case GTK_STATE_SELECTED: + case GTK_STATE_INSENSITIVE: + break; + default: + gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED); + break; + } } static void @@ -628,10 +619,8 @@ gtk_real_list_item_deselect (GtkItem *item) g_return_if_fail (item != NULL); g_return_if_fail (GTK_IS_LIST_ITEM (item)); - if (GTK_WIDGET (item)->state == GTK_STATE_NORMAL) - return; - - gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL); + if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED) + gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL); } static void @@ -640,129 +629,15 @@ gtk_real_list_item_toggle (GtkItem *item) g_return_if_fail (item != NULL); g_return_if_fail (GTK_IS_LIST_ITEM (item)); - if (GTK_WIDGET (item)->parent && GTK_IS_LIST (GTK_WIDGET (item)->parent)) - gtk_list_select_child (GTK_LIST (GTK_WIDGET (item)->parent), - GTK_WIDGET (item)); - else + switch (GTK_WIDGET (item)->state) { - /* Should we really bother with this bit? A listitem not in a list? - * -Johannes Keukelaar - * yes, always be on the save side! - * -timj - */ - if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED) - gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL); - else - gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED); + case GTK_STATE_SELECTED: + gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL); + break; + case GTK_STATE_INSENSITIVE: + break; + default: + gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED); + break; } } - -static void -gtk_list_item_toggle_focus_row (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_toggle_focus_row (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_select_all (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_select_all (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_unselect_all (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_unselect_all (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_undo_selection (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_undo_selection (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_start_selection (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_start_selection (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_end_selection (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_end_selection (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} - -static void -gtk_list_item_extend_selection (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position, - gboolean auto_start_selection) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_extend_selection (GTK_LIST (GTK_WIDGET (list_item)->parent), - scroll_type, position, auto_start_selection); -} - -static void -gtk_list_item_scroll_horizontal (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_scroll_horizontal (GTK_LIST (GTK_WIDGET (list_item)->parent), - scroll_type, position); -} - -static void -gtk_list_item_scroll_vertical (GtkListItem *list_item, - GtkScrollType scroll_type, - gfloat position) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_scroll_vertical (GTK_LIST (GTK_WIDGET (list_item)->parent), - scroll_type, position); -} - -static void -gtk_list_item_toggle_add_mode (GtkListItem *list_item) -{ - g_return_if_fail (list_item != 0); - g_return_if_fail (GTK_IS_LIST_ITEM (list_item)); - - if (GTK_IS_LIST (GTK_WIDGET (list_item)->parent)) - gtk_list_toggle_add_mode (GTK_LIST (GTK_WIDGET (list_item)->parent)); -} -- 2.30.2